package menuServer

import (
	"fmt"
	"log"
	"net/http"
	"path"
	"path/filepath"
	"strings"
	"sync"
	"video/global"

	"github.com/gin-gonic/gin"
)

type Area struct {
	Name       string `json:"name"`
	RegionUuid int    `json:"regionUuid"`
}

type Equipment struct {
	DeviceDesc string `json:"deviceDesc"`
	LiveUrl    string `json:"liveUrl"`
}

type MenuServer struct {
	Port          int
	AreaList      []Area
	EquipmentList [][]Equipment
	Service       *gin.Engine
}

func createAreaList() []Area {

	areaList := []Area{}

	for index, videoServer := range global.VideoServerPool.Pool {
		areaList = append(areaList, Area{
			Name:       fmt.Sprintf("%s:%d", global.HOST, videoServer.Port),
			RegionUuid: index,
		})

	}

	return areaList

}

func createEquipmentList() [][]Equipment {

	result := [][]Equipment{}

	for _, server := range global.VideoServerPool.Pool {

		areaItem := []Equipment{}

		for index, videoPath := range server.VideoPathList {

			filenameWithSuffix := filepath.Base(videoPath)
			fileSuffix := path.Ext(filenameWithSuffix)
			filename := strings.TrimSuffix(filenameWithSuffix, fileSuffix)

			fmt.Println(filenameWithSuffix, fileSuffix, filename)

			areaItem = append(areaItem, Equipment{
				DeviceDesc: filename,
				LiveUrl:    fmt.Sprintf("http://%s:%d/video/%d", global.HOST, server.Port, index),
			})
		}

		result = append(result, areaItem)
	}

	return result
}

func CreateMenuerver(port int) *MenuServer {

	menuServer := &MenuServer{
		Port:          port,
		AreaList:      createAreaList(),
		EquipmentList: createEquipmentList(),
		Service:       gin.New(),
	}

	menuServer.Service.Use(middle(menuServer))

	device := menuServer.Service.Group("/device")
	{
		device.POST("/monitorRegions/list", AreaList)
		device.POST("/monitorDeviceByRegionId/list", EquipmentList)
		device.POST("/monitorRegions/device/list", AllEquipments)
	}

	return menuServer
}

func (m *MenuServer) Run(wg *sync.WaitGroup) {
	wg.Add(1)

	go func() {
		defer wg.Done()
		log.Println(fmt.Sprintf("menu server: %d", m.Port))
		m.Service.Run(fmt.Sprintf(":%d", m.Port))
	}()
}

func middle(s *MenuServer) gin.HandlerFunc {
	return func(c *gin.Context) {

		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT")

		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(204)
			return
		}

		c.Set("server", s)
		c.Next()
	}
}

func AreaList(c *gin.Context) {

	var server *MenuServer

	if s, exists := c.Get("server"); exists {
		var ok bool
		server, ok = s.(*MenuServer)

		if !ok {
			log.Fatal("not funed Server")
		}
	}

	fmt.Printf("send: ", *server)

	c.JSON(http.StatusOK, gin.H{
		"msg":    "OK",
		"ok":     true,
		"result": server.AreaList,
	})
}

type EquipmentListRequst struct {
	RegionUuid int `json:"regionUuid"`
}

func EquipmentList(c *gin.Context) {

	var server *MenuServer

	var requst EquipmentListRequst

	if err := c.BindJSON(&requst); err != nil {
		log.Println("error: ", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": err,
		})
		return
	}

	fmt.Println(requst.RegionUuid)

	if s, exists := c.Get("server"); exists {
		var ok bool
		server, ok = s.(*MenuServer)

		if !ok {
			log.Fatal("not funed Server")
		}
	}

	if requst.RegionUuid >= len(server.EquipmentList) {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": "切片越界",
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"msg":    "OK",
		"ok":     true,
		"result": server.EquipmentList[requst.RegionUuid],
	})
}

func AllEquipments(c *gin.Context) {

	var server *MenuServer

	var requst EquipmentListRequst

	if err := c.BindJSON(&requst); err != nil {
		log.Println("error: ", err)
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": err,
		})
		return
	}

	fmt.Println(requst.RegionUuid)

	if s, exists := c.Get("server"); exists {
		var ok bool
		server, ok = s.(*MenuServer)

		if !ok {
			log.Fatal("not funed Server")
		}
	}

	if requst.RegionUuid >= len(server.EquipmentList) {
		c.JSON(http.StatusInternalServerError, gin.H{
			"msg": "切片越界",
		})
		return
	}

	resultItem := map[string]interface{}{
		"communityName":     "xxx",
		"monitorDeviceDTOS": server.EquipmentList[requst.RegionUuid],
	}

	c.JSON(http.StatusOK, gin.H{
		"msg":    "OK",
		"ok":     true,
		"result": []interface{}{resultItem, resultItem},
	})
}
